/**
 * MiniGolf Scorecard
 * Copyright (C) 2010  MiriTheQuiet, http://minigolfscorecard.googlecode.com/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package cz.mtq.mgsc.view;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;

import cz.mtq.mgsc.MgscMidlet;
import cz.mtq.mgsc.Settings;
import cz.mtq.mgsc.command.AbstractCommand;
import cz.mtq.mgsc.model.Player;
import cz.mtq.mgsc.model.Players;

public class GameOptionsScreen {

	// number of players text field
	private final TextField playersTf = new TextField(Settings.getResource(Settings.TEXT_NUMBER_OF_PLAYERS), "1", 2, TextField.NUMERIC);
	// form
	private final Form f = new Form(Settings.getResource(Settings.TEXT_APP_NAME));

	private final MgscMidlet midlet;
	private final AbstractCommand gameOptionsScreenPlay;
	private final AbstractCommand gameOptionsScreenExit;

	private Alert canvasExitConfirmationAlert;
	private ScoreCardCanvas scc;

	private int playerIndex = 0;

	/**
	 * shows form with textfield for entering number of players
	 * Sets commands Exit (terminates app), OK and listener which invokes
	 * {@link #setResultsScreen(MgscMidlet)}
	 */
	public void setPlayersScreen() {
		// languages
		final ChoiceGroup languages = new ChoiceGroup(Settings.getResource(Settings.TEXT_LANGUAGE), Choice.EXCLUSIVE, new String[] { "Česky",
				"English" }, null);
		languages.setLayout(Item.LAYOUT_LEFT);
		f.append(languages);
		// mode layout
		// number of players text field
		playersTf.setLayout(Item.LAYOUT_LEFT);
		f.append(playersTf);
		// input for player name
		final TextField player = createNewPlayerNameInput();

		f.append(player);
		// item change listener
		f.setItemStateListener(new ItemStateListener() {

			public void itemStateChanged(Item item) {
				if (playersTf == item) {
					String value = playersTf.getString();
					if (value != null) {
						value = value.trim();
						if (!value.equals("") && !value.equals("0")) {
							int numberOfPlayers = Integer.parseInt(value);
							if (numberOfPlayers > 0) {
								int numberOfPlayersTextFields = getNumberOfPlayerTextFields(f);
								if (numberOfPlayers > numberOfPlayersTextFields) {
									// add the textfields
									for (int itemsToAdd = numberOfPlayers - numberOfPlayersTextFields; itemsToAdd > 0; itemsToAdd--) {
										f.append(createNewPlayerNameInput());
									}
								} else if (numberOfPlayers < numberOfPlayersTextFields) {
									// remove some textfields
									for (int itemsToRemove = -(numberOfPlayers - numberOfPlayersTextFields); itemsToRemove > 0; itemsToRemove--) {
										f.delete(f.size() - 1);
										playerIndex--;
									}
								}
							}
						}
					}
				}
				if (item == languages) {
					// TODO remove hardcoded languages and locales
					if ("Česky".equals(languages.getString(languages.getSelectedIndex()))) {
						// czech
						Settings.setResoureBundleLocale("cs");
					} else {
						// english
						Settings.setResoureBundleLocale("en");
					}
					// we must change the commands cause it is not possible to change its
					// label
					midlet.removeCommand(f, gameOptionsScreenExit);
					midlet.removeCommand(f, gameOptionsScreenPlay);
					gameOptionsScreenExit.setCommand(GameOptionsScreen.this.getThisScreenExitCommand());
					gameOptionsScreenPlay.setCommand(GameOptionsScreen.this.getThisScreenPlayCommand());
					midlet.addCommand(f, gameOptionsScreenExit);
					midlet.addCommand(f, gameOptionsScreenPlay);
					// for each item translate labels
					// TODO prilis hardcoded zmena labels u komponent!!!
					for (int i = 0; i < f.size(); i++) {
						Item fItem = f.get(i);
						if (i == 0) {
							// zmenit navic items
							ChoiceGroup lang = (ChoiceGroup) fItem;
							lang.setLabel(Settings.getResource(Settings.TEXT_LANGUAGE));
						} else if (i == 1) {
							// zmenit navic items
							fItem.setLabel(Settings.getResource(Settings.TEXT_NUMBER_OF_PLAYERS));
						} else {
							translatePlayerTextFieldLabel(fItem);
						}
					}
				}
			}
		});
		// listener
		f.setCommandListener(midlet);
		// commands
		midlet.addCommand(f, gameOptionsScreenPlay);
		midlet.addCommand(f, gameOptionsScreenExit);
		midlet.setCurrent(f);
	}

	private void translatePlayerTextFieldLabel(Item tf) {
		String label = tf.getLabel();
		StringBuffer sb = new StringBuffer(Settings.getResource(Settings.TEXT_PLAYERS_NAME));
		tf.setLabel(sb.append(label.substring(label.lastIndexOf(' '))).toString());
	}

	private int getNumberOfPlayerTextFields(Form f) {
		int playersTextFields = 0;
		String playersTextFieldLabel = Settings.getResource(Settings.TEXT_PLAYERS_NAME);
		for (int i = 0; i < f.size(); i++) {
			Item item = f.get(i);
			if (item instanceof TextField && item.getLabel().startsWith(playersTextFieldLabel)) {
				playersTextFields++;
			}
		}
		return playersTextFields;
	}

	private int getIndexOfFirstPlayerTextField(Form f) {
		String playersTextFieldLabel = Settings.getResource(Settings.TEXT_PLAYERS_NAME);
		for (int i = 0; i < f.size(); i++) {
			Item item = f.get(i);
			if (item instanceof TextField && item.getLabel().startsWith(playersTextFieldLabel)) {
				return i;
			}
		}
		return -1;
	}

	private TextField createNewPlayerNameInput() {
		StringBuffer sb = new StringBuffer(Settings.getResource(Settings.TEXT_PLAYERS_NAME));
		sb.append(" ");
		sb.append(++playerIndex);
		TextField player = new TextField(sb.toString(), "", Settings.MAX_NAME_LENGTH, TextField.ANY);
		player.setLayout(Item.LAYOUT_LEFT/* |Item.LAYOUT_VCENTER */);
		return player;
	}

	/**
	 * TODO optimize!
	 * 
	 * @return
	 */
	private Command getThisScreenExitCommand() {
		return new Command(Settings.getResource(Settings.TEXT_EXIT), Command.EXIT, 1);
	}

	private Command getThisScreenPlayCommand() {
		return new Command(Settings.getResource(Settings.TEXT_PLAY), Command.OK, 0);
	}

	private Command getThisScreenYesCommand() {
		return new Command(Settings.getResource(Settings.TEXT_YES), Command.EXIT, 1);
	}

	private Command getThisScreenNoCommand() {
		return new Command(Settings.getResource(Settings.TEXT_NO), Command.OK, 0);
	}

	public Alert getCanvasExitConfirmationAlert() {
		if (canvasExitConfirmationAlert == null) {
			canvasExitConfirmationAlert = new Alert(Settings.getResource(Settings.TEXT_APP_NAME), Settings.getResource(Settings.TEXT_EXIT_CONFIRM),
					null, AlertType.CONFIRMATION);
			canvasExitConfirmationAlert.setCommandListener(midlet);
			// exit cmd
			midlet.addCommand(canvasExitConfirmationAlert, new AbstractCommand(getThisScreenYesCommand(), midlet) {
				protected void exec() throws Exception {
					GameOptionsScreen.this.midlet.notifyDestroyed();
				}
			});
			// continue cmd
			midlet.addCommand(canvasExitConfirmationAlert, new AbstractCommand(getThisScreenNoCommand(), midlet) {
				protected void exec() throws Exception {
					scc.setFullScreenMode(true);
					midlet.setCurrent(scc);
				}
			});
		}
		return canvasExitConfirmationAlert;
	}

	public GameOptionsScreen(MgscMidlet midlet) {
		this.midlet = midlet;
		gameOptionsScreenPlay = new cz.mtq.mgsc.command.AbstractCommand(this.getThisScreenPlayCommand(), midlet) {

			/**
			 * Shows score card
			 * sets command OK and listener which starts "the game"
			 * sets command Exit which terminates the application
			 * sets command Back which returns to welcome screen - this must be done
			 * with care, no objects init again, reuse the old ones!
			 */
			public void exec() throws Exception {
				Players players = GameOptionsScreen.this.midlet.getPlayers();
				// get the number of players
				players.initPlayers(Byte.parseByte(playersTf.getString()));
				int indexOfFirstPlayerTextField = getIndexOfFirstPlayerTextField(f);
				if (indexOfFirstPlayerTextField > -1) {
					// just test if there can be any textfield for name
					for (int i = indexOfFirstPlayerTextField; i < f.size(); i++) {
						Item item = f.get(i);
						if (item instanceof TextField) {
							TextField tf = (TextField) item;
							String userName = tf.getString();
							if (userName != null && !userName.equals("")) {
								players.addPlayer(new Player(userName));
							}
						}
					}
				}
				if (players.size() > 0) {
					scc = new ScoreCardCanvas(getMidlet());
					// add Exit command
					getMidlet().addCommand(scc,
							new cz.mtq.mgsc.command.AbstractCommand(new Command(Settings.getResource(Settings.TEXT_EXIT), Command.EXIT, 3), getMidlet()) {

								public void exec() throws Exception {
									GameOptionsScreen.this.midlet.setCurrent(getCanvasExitConfirmationAlert());
								}

							});
					//clear bundle cache, we just need the "current"
					Settings.clearResourceBundleCache();
					//set displayable
					getMidlet().setCurrent(scc);
					// TODO remove PLAY and EXIT command of previous screen
				}

			}
		};
		gameOptionsScreenExit = new cz.mtq.mgsc.command.AbstractCommand(this.getThisScreenExitCommand(), midlet) {

			public void exec() throws Exception {
				GameOptionsScreen.this.midlet.notifyDestroyed();
			}

		};
	}
}
